#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <Rcpp.h>

using namespace std;
using namespace Rcpp;

HINSTANCE hdll2 = 0;
typedef int(*funcCreateWebView)(HWND, char*, int);
typedef int(*funcResizeWebView)(HWND);
typedef int(*funcExecuteScript)(char*);
typedef int(*funcGetCacheText)(char*);
funcCreateWebView m_funcCreateWebView;
funcResizeWebView m_funcResizeWebView;
funcExecuteScript m_funcExecuteScript;
funcGetCacheText m_funcGetCacheText;


HWND m_hWnd;
HINSTANCE hInst;
bool m_hasMsg1 = false;
int m_hasMsg2 = 0;
int m_hasMsg3 = 0;
std::string m_programDir;
std::string m_htmlPath;
int m_timerID = 0;

void Init2()
{
  std::string path2 = m_programDir + "//facecatbridge.dll";
  hdll2 = LoadLibraryA(path2.c_str());
  printf(path2.c_str());
  
  m_funcCreateWebView = (funcCreateWebView)GetProcAddress(hdll2, "createWebView");
  m_funcResizeWebView = (funcResizeWebView)GetProcAddress(hdll2, "resizeWebView");
  m_funcExecuteScript = (funcExecuteScript)GetProcAddress(hdll2, "executeScript");
  m_funcGetCacheText = (funcExecuteScript)GetProcAddress(hdll2, "getCacheText");
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
  if(message == WM_SETCURSOR)
  {
    if((int)lParam == 33554433)
    {
      return 1;
    }
  }
  else if(message == WM_SIZE){
    m_funcResizeWebView(hWnd);
  }else if(message == 0x0402){
    //printf("navigateok");
    //m_funcExecuteScript("sendDataToHtml(\"cpp data\")");
    ShowWindow(hWnd, SW_SHOWMAXIMIZED);
    m_hasMsg1 = true;
  }else if(message == 0x0401){
    m_hasMsg2++;
  }else if (message == WM_TIMER){
    if(int(wParam) == m_timerID){
      m_hasMsg3++;
    }
  }
  switch (message)
  {
    //处理关闭窗口的消息
  case WM_CLOSE:
  {
    DestroyWindow(hWnd);
    PostQuitMessage(0);
    break;
  }
  default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}

ATOM MyRegisterClass(HINSTANCE hInstance){
  WNDCLASSEX wcex;
  wcex.cbSize = sizeof(wcex);
  wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  wcex.lpfnWndProc	= WndProc;
  wcex.cbClsExtra		= 0;
  wcex.cbWndExtra		= 0;
  wcex.hInstance		= hInstance;
  //wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
  wcex.hCursor		= LoadCursor(0, IDC_ARROW);
  wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName	= 0;
  wcex.lpszClassName  = "facecat_r";
  wcex.hIconSm		= 0; 
  return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
  HWND hWnd;
  hInst = hInstance; // 将实例句柄存储在全局变量中
  hWnd = CreateWindow("facecat_r", "facecat_r", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                      CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);
  if (!hWnd)
  {
    return FALSE;
  }
  m_hWnd = hWnd;
  UpdateWindow(m_hWnd);
  ShowWindow(hWnd, SW_SHOWNORMAL);
  UpdateWindow(hWnd);
  m_funcCreateWebView(hWnd, (char*)m_htmlPath.c_str(), 1);
  return TRUE;
}

MSG *m_msg = new MSG;

int exec(HINSTANCE hInstance, int nCmdShow){
  MyRegisterClass(hInstance);
  // 执行应用程序初始化:
  if (!InitInstance (hInstance, nCmdShow))
  {
    return FALSE;
  }
  MSG msg;
  while (GetMessage(&msg, 0, 0, 0))
  {
    if (!TranslateAccelerator(msg.hwnd, 0, &msg))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    break;
  }
  
  return 0;
}

// [[Rcpp::export]]
int startTimer(int id, int tick)
{
  m_timerID = id;
  SetTimer(m_hWnd, m_timerID, tick, 0);
  return 0;
}

// [[Rcpp::export]]
int setProgramDir(string dir)
{
  m_programDir = dir;
  return 0;
}

// [[Rcpp::export]]
int executeScript(string script)
{
  return m_funcExecuteScript((char*)script.c_str());
}

// [[Rcpp::export]] 
int showWindow(string htmlPath)
{
  if(!hdll2)
  {
    Init2();
  }
  m_htmlPath = htmlPath;
  return exec(0, SW_SHOW);
}

// [[Rcpp::export]]
int getMessage(){
  bool result = GetMessage(m_msg, 0, 0, 0);
  if(result){
    return 1;
  }else{
    return 0;
  }
}

// [[Rcpp::export]]
int doMessage(){
  if (!TranslateAccelerator(m_msg->hwnd, 0, m_msg))
  {
    TranslateMessage(m_msg);
    DispatchMessage(m_msg);
  }
  if(m_hasMsg1){
    m_hasMsg1 = false;
    return 1;
  }else if(m_hasMsg2 > 0){
    m_hasMsg2--;
    return 2;
  }else if(m_hasMsg3 > 0){
    m_hasMsg3--;
    return 3;
  }else{
    return 0;
  }
}

// [[Rcpp::export]]
CharacterVector getCacheText()
{
  char sz[102400] = {0};
  m_funcGetCacheText(sz);
  return std::string(sz);
}



